package server;
import java.io.*;
import java.net.*;
import java.util.Vector;
/**
 * This is the Main class of the server, responsible for listening for incoming connections and assigning Connection Handlers for each new connection
 * @author yariv zur
 */
class WorkManager implements Runnable {
	ServerSocket serverSocket;
	ProtocolFactory protocolFactory;
	int listenPort;

	/**
	 * Constructor for the WorkManager class
	 * @param port given port to listen on
	 * @param pf - given protocol factory to instantiate the protocol
	 */
	public WorkManager(int port, ProtocolFactory pf) {
		serverSocket = null;
		listenPort = port;
		protocolFactory = pf;
		Globals.nonSubmittedJobs = new Vector<Job>(0);
		Globals.submittedJobs = new Vector<Job>(0);
		Globals.finishedJobs = new Vector<Job>(0);
		Globals.resources = new Vector<Resource>(0);
	}
	/**
	 * The life-cycle of the work manager:
	 * 1. listen on the socket
	 * 2. once a connection is made, create a new Connection Handler and assign it to take care of the connection
	 * 3.go back to listening on the port, as long as the shutdown command was not given - in which case exit
	 */
	public void run() {
		System.out.println("The WorkManager has entered the running state!");
		try {
			serverSocket = new ServerSocket(listenPort);
		} catch (IOException e) {
			System.out.println("Cannot listen on port " + listenPort);
		}
		while (!Globals.SHUTDOWN) {
			try {
				Socket s = serverSocket.accept();
				Tokenizer tokenizer = new MessageTokenizer(new BufferedInputStream((s.getInputStream())));
				ConnectionHandler newConnection = new ConnectionHandler(s, protocolFactory.create(), tokenizer);
				new Thread(newConnection).start();
			} catch (IOException e) {
				if(e.toString().equals("UnsupportedEncodingException")){
					System.out.println("The tokenizer could not be created");
				}
				else{
					System.out.println("Failed to accept on port " + listenPort);
				}
			}
		}
		System.out.println("The shutdown command has been received");
		try{
			close();
		}
		catch (Exception e){
			System.out.println("Server socket could not close gracefully");
		}
	}


	/**
	 * Closes the socket the server is listening on
	 * @throws IOException
	 */
	public void close() throws IOException {
		serverSocket.close();
	}
	/**
	 * The main method, responsible for creating the photos directory and initializing the work manager
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		// Get port
		int port = Integer.decode(args[0]).intValue();
		File dir = new File("photos");
		if(!dir.exists()){
			boolean dirCreated = dir.mkdir();
			if(!dirCreated){
				System.out.println("Unable to create the photos folder!");
				return;
			}
		}
		Globals.PATH = dir.getPath();
		WorkManager server = new WorkManager(port, new MessageHandlerFactory());
		Thread serverThread = new Thread(server);
		serverThread.start();
		try {
			serverThread.join();
		} catch (InterruptedException e) {
			System.out.println("Server stopped");
		}
	}
}
